﻿using LPBToolsLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace StationSer
{
    public class StationsServer
    {
        public static JSONINISettings StationServerCFG { get; set; } = null;
        public Recorder_Error SysErr { get; set; } = null;
        public Recorder_RunLog RunLog { get; set; } = null;
        /// <summary>
        /// 线程锁字符串
        /// </summary>
        private static string sUniquKey = "StationsServer_20221203" + Guid.NewGuid().ToString();
        /// <summary>
        /// 线程锁
        /// </summary>
        private Mutex thdMutex { get; } = new Mutex(false, sUniquKey);

        private bool iThdRun = false;
        private Thread thdMain = null;
        /// <summary>
        /// 工作站对象字典
        /// </summary>
        protected Dictionary<string, IFDExCommunicater> tStationsList { get; } = new Dictionary<string, IFDExCommunicater>();
        public void CloseAll()
        {
            iThdRun = false;
            Thread.Sleep(20);
        }
        #region 反馈在线工作站及通讯通道情况
        /// <summary>
        /// 当前在线工作站数量
        /// </summary>
        public int StationCount { get { return tStationsList.Count; } }
        /// <summary>
        /// 当前在线的工作站列表
        /// </summary>
        public string[] StationsIDList { get { return tStationsList.Keys.ToArray(); } }
        /// <summary>
        /// 根据提供的StationID，返回对应的通讯接口及工作站
        /// </summary>
        /// <param name="StationID"></param>
        /// <returns></returns>
        public IFDExCommunicater getStation(string StationID)
        {
            thdMutex.WaitOne();
            try
            {
                if (tStationsList.ContainsKey(StationID))
                    return tStationsList[StationID];
            }
            finally
            {
                thdMutex.ReleaseMutex();
            }
            return null;
        }

        public bool getStation(string StationID,out IFDExCommunicater tCommunicater)
        {
            tCommunicater = null;
            thdMutex.WaitOne();
            try
            {
                if (tStationsList.ContainsKey(StationID))
                    tCommunicater= tStationsList[StationID];
            }
            finally
            {
                thdMutex.ReleaseMutex();
            }
            return tCommunicater!=null;
        }
        #endregion

        /// <summary>
        /// 根据收到的数据包，创建对应的通讯接口，并返回应答包
        /// </summary>
        /// <param name="tRecPacket"></param>
        /// <returns></returns>
        public DExRespon StationCommunicate(DExPacket tRecPacket)
        {
            if ((tRecPacket != null) && (!string.IsNullOrEmpty(tRecPacket.StatioinID)))
            {
                string sStaID = tRecPacket.StatioinID;
                thdMutex.WaitOne();
                try
                {
                    if (!tStationsList.ContainsKey(sStaID))
                    {
                        DExPacketCommunicate tCommunicate = new DExPacketCommunicate(sStaID);
                        tCommunicate.RunLog = RunLog;
                        tCommunicate.SysErr = SysErr;
                        tStationsList.Add(sStaID, tCommunicate);
                    }
                }
                finally
                {
                    thdMutex.ReleaseMutex();
                }
                //tStationsList[sStaID].run
                return tStationsList[sStaID].receNewPacket(tRecPacket);
            }
            return null;
        }

        public StationsServer()
        {
            thdMain = new Thread(thdMainRun);
            iThdRun = true;
            thdMain.Start();
        }

        private void thdMainRun()
        {
            while (iThdRun)
                try
                {
                    List<string> tDelStaID = new List<string>();
                    foreach (KeyValuePair<string, IFDExCommunicater> item in tStationsList)
                        if (item.Value.IsTimeOut)
                            tDelStaID.Add(item.Key);
                    thdMutex.WaitOne();
                    try
                    {
                        foreach (string StaID in tDelStaID)
                            tStationsList.Remove(StaID);
                    }
                    finally
                    {
                        thdMutex.ReleaseMutex();
                    }
                }

                catch (Exception ex)
                {
                    SysErr?.setRecord(ex);
                }
                finally
                {
                    Thread.Sleep(10);
                }
        }
    }
}
